﻿/*
 * author:漠然 2013年7月12日4:25:15
 * ConfigManager 作用：
 *  1.对配置XML文件进行统一管理
 *  2.对配置文件进行持久化存储
 */

using System;
using System.Collections.Generic;
using System.IO;
using System.Reflection;
using System.Windows.Forms;
using System.Xml.Linq;
using System.Xml.XPath;

namespace Mrsoft.Update.Common
{
    /// <summary>
    /// 配置数据实际读写
    /// 采用的是XML的方式
    /// </summary>
    internal static class ConfigManager
    {
        #region 根节点

        private const string rootName = "Config";

        #endregion

        #region 将XML文件缓存到内存之中

        private static readonly Dictionary<string, XDocument> XDocs = new Dictionary<string, XDocument>();

        private static XDocument GetxDoc(string fileName)
        {
            fileName = fileName.Replace("/", "\\");
            //原子操作
            lock (XDocs)
            {
                XDocument xDoc;
                if (!XDocs.TryGetValue(fileName, out xDoc))
                {
                    try
                    {
                        xDoc = XDocument.Load(fileName);
                    }
                    catch
                    {
                        string filePath = fileName.Remove(fileName.LastIndexOf(@"\", StringComparison.Ordinal));
                        if (!Directory.Exists(filePath))
                            Directory.CreateDirectory(filePath);
                        xDoc = new XDocument();
                        xDoc.AddFirst(new XElement(rootName));
                        xDoc.Save(fileName);
                    }
                    XDocs.Add(fileName, xDoc);
                }
                return xDoc;
            }
        }

        #endregion

        public static bool GetValue<T>(string dbfile, string xPath, ref T value)
        {
            var xDoc = GetxDoc(dbfile);
            if (xDoc.Root != null)
            {
                var xElement = xDoc.Root.XPathSelectElement("./" + xPath);
                if (xElement == null)
                {
                    return false;
                }
                var result = xElement.Value;
                if (string.IsNullOrEmpty(result))
                    return false;
                if (value is string)
                {
                    value = (T)(object)result;
                    return true;
                }
                try
                {
                    //使用标准的Parse模块进行
                    value = (T)typeof(T).InvokeMember("Parse", BindingFlags.InvokeMethod, null, null, new[] { result });
                    return true;
                }
                catch (Exception ex) { Console.WriteLine("{0}", ex.Message); }
            }
            return false;
        }

        public static void SetValue<T>(string dbfile, string xPath, T value)
        {
            //统一分割符号
            dbfile = dbfile.Replace("\\", "/");
            //从Memory中加载到XML的DOM
            var xDoc = GetxDoc(dbfile);
            //尝试直接定位 如果定位成功表示存在这样的节点 否则逐级检查
            if (xDoc.Root != null)
            {
                var xElement = xDoc.Root.XPathSelectElement("./" + xPath);
                if (xElement == null)
                {
                    var keys = xPath.Split('/');
                    xElement = xDoc.Root;
                    foreach (string key in keys)
                    {
                        if (xElement != null)
                        {
                            var tElement = xElement.Element(key);
                            if (tElement == null)
                            {
                                tElement = new XElement(key);
                                xElement.Add(tElement);
                            }
                            xElement = tElement;
                        }
                    }
                }
                //存储
                if (xElement != null)
                {
                    xElement.SetValue(value);
                }
                xDoc.Save(dbfile);
            }
        }  
    }
}
